<template>
  <div :class="['flex-column', props.modal ? 'modal' : '']" v-if="props.modelValue">
    <div
      class="v-window-container"
      ref="dragWin"
      :id="state.id"
      :style="[
        {
          width: state.initWidth,
          height: state.initHeight,
          left: state.initLeft,
          top: state.initTop,
          'border-color': theme.color,
        },
        mainStyle,
      ]"
    >
      <div class="v-window-title" @pointerdown="MakeDragable" :style="{ background: theme.color, color: '#fff' }">
        <div style="width: auto; padding-left: 5px; font-size: 14px">
          <slot name="head">{{ title }}</slot>
        </div>
        <div style="width: auto">
          <!--
            <button class="v-window-btn" @click="win_refresh"
            ><el-icon><Refresh /></el-icon
            ></button>
            -->
          <button v-if="state.minimize" class="v-window-btn" @click="win_min"
            ><el-icon> <Minus /> </el-icon
          ></button>
          <button v-if="state.maxmize" class="v-window-btn" @click="win_max"
            ><el-icon> <FullScreen /> </el-icon
          ></button>
          <button v-if="state.closable" class="v-window-btn" @click="win_close"
            ><el-icon> <Close /> </el-icon
          ></button>
        </div>
      </div>
      <div class="v-window-body">
        <div class="v-window-content" :style="hasFootHeight"><slot></slot></div>
        <div class="v-window-footer" v-if="state.footer">
          <slot name="footer">
            <el-button @click="cancel">取 消</el-button>
            <el-button type="primary" @click="confirm" :loading="props.loading">保 存</el-button>
          </slot>
        </div>
      </div>
      <div v-if="state.resizable" class="v-window-resizable" @pointerdown="MakeResizable"></div>
    </div>
  </div>
</template>

<script setup>
  import {
    ref,
    reactive,
    getCurrentInstance,
    computed,
    onBeforeMount, // 在组件挂载之前执行的函数
    onMounted,
    onBeforeUpdate, // 在组件修改之前执行的函数
    onUpdated,
    watch,
    provide,
    nextTick,
  } from 'vue'
  import { useAppStore } from '@v-model/shared--stores'
  import { onDeactivated } from 'vue'

  defineOptions({ name: 'VWindow' })

  const AppStore = useAppStore()
  const theme = computed(() => AppStore.GET_THEME())

  const { proxy } = getCurrentInstance()
  const _this = proxy

  const props = defineProps({
    modelValue: Boolean,
    modal: {
      type: [Boolean, String],
      default: false,
    },
    mainStyle: Object,
    title: {
      type: [String],
    },
    initWidth: {
      type: String,
      default: '300px',
    }, //初始宽度
    initHeight: {
      type: String,
      default: '200px',
    }, //初始高度
    minWidth: {
      type: String,
      default: '100px',
    },
    minHeight: {
      type: String,
      default: '100px',
    },
    initLeft: {
      type: String,
      default: '10vw',
    }, //初始左边距
    initTop: {
      type: String,
      default: '10vh',
    }, //初始上边距
    closable: {
      type: [Boolean, String],
      default: true,
    }, //能否关闭
    resizable: {
      type: [Boolean, String],
      default: true,
    }, //能否缩放
    maxable: {
      type: [Boolean, String],
      default: true,
    }, //能否缩放
    defaultMax: {
      type: [Boolean, String],
      default: false,
    }, //默认最大化
    onclose: {
      type: Function,
      default: null,
    },
    onresize: {
      type: Function,
      default: null,
    },
    onfocus: {
      type: Function,
      default: null,
    },
    // 是否开启默认 确认取消按钮
    footer: {
      type: Boolean,
      default: false,
    },
    // loading 动画加载
    loading: {
      type: Boolean,
      default: false,
    },
    // 取消是否取消操作用户自定义
    isVerify: {
      type: Boolean,
      default: false,
    },
  })

  const state = reactive({
    id: _this.$tool.guid(),
    initWidth: props.initWidth,
    initHeight: props.initHeight,
    initLeft: `50vw - ${props.initWidth / 2}`,
    initTop: `50vw - ${props.initTop / 2}`,
    resizable: props.resizable,
    closable: props.closable,
    minimize: false,
    maxmize: props.maxable,
    footer: props.footer,
    loading: props.loading,
  })
  watch(
    () => props.initHeight,
    (val) => {
      state.initHeight = val
    }
  )
  const hasFootHeight = computed(() => (props.footer ? { height: `calc(100% - 40px)` } : null))

  //获取窗口实体
  const dragWin = ref(null)
  const win_refresh = function (e) {
    _this.$forceUpdate()
  }
  const win_min = function (e) {
    state.minimize = false
    state.maxmize = true
    nextTick(() => {
      const CtlEl = dragWin.value
      CtlEl.style.left = state.initLeft
      CtlEl.style.top = state.initTop
      CtlEl.style.width = state.initWidth
      CtlEl.style.height = state.initHeight

      if (typeof props.onresize == 'function') {
        props.onresize(CtlEl.offsetWidth, CtlEl.offsetHeight)
      }
    })
  }
  const win_max = function (e) {
    state.minimize = true
    state.maxmize = false
    nextTick(() => {
      const CtlEl = dragWin.value
      const clientWidth = document.documentElement.clientWidth //页面的宽
      const clientHeight = document.documentElement.clientHeight //页面的高

      CtlEl.style.left = 0
      CtlEl.style.top = 0
      CtlEl.style.width = clientWidth + 'px'
      CtlEl.style.height = clientHeight + 'px'

      if (typeof props.onresize == 'function') {
        props.onresize(CtlEl.offsetWidth, CtlEl.offsetHeight)
      }
    })
  }

  const MakeResizable = function (e) {
    var eve = e || window.event
    var pointerId = e.pointerId
    const dragbar = e.target
    const CtlEl = dragWin.value
    if (typeof dragbar.setPointerCapture != 'undefined') {
      //SetCapture捕捉鼠标到指定的元素
      //dragAry.setCapture();
      dragbar.setPointerCapture(pointerId)
    }
    if (typeof dragbar.setPointerCapture != 'undefined') {
      //SetCapture捕捉鼠标到指定的元素
      //dragAry.setCapture();
      dragbar.setPointerCapture(pointerId)
    }
    let ElPos = {
      __point_s_x__: e.clientX, //点击鼠标时储存x轴
      __point_s_y__: e.clientY, //点击鼠标时储存y轴
      __e_rect_x__: CtlEl.offsetLeft,
      __e_rect_y__: CtlEl.offsetTop,
      __e_rect_w__: CtlEl.offsetWidth,
      __e_rect_h__: CtlEl.offsetHeight,
    }
    document.onmousemove = function (e) {
      var e = e || window.event
      if (e.preventDefault) {
        e.preventDefault()
      }
      const CtlEl = dragWin.value
      var iE = e
      if (iE.clientY == 0) {
        //向左移动
        state.initWidth = ElPos.__e_rect_w__ + (iE.clientX - ElPos.__point_s_x__) + 'px'
      } else if (iE.clientX == 0) {
        //向右移动
        state.initHeight = ElPos.__e_rect_h__ + (iE.clientY - ElPos.__point_s_y__) + 'px'
      } else if (iE.clientY != 0 && iE.clientX != 0) {
        //同时移动
        state.initWidth = ElPos.__e_rect_w__ + (iE.clientX - ElPos.__point_s_x__) + 'px'
        state.initHeight = ElPos.__e_rect_h__ + (iE.clientY - ElPos.__point_s_y__) + 'px'
      }
      if (typeof props.onresize == 'function') {
        props.onresize(CtlEl.offsetWidth, CtlEl.offsetHeight)
      }
    }
    document.onmouseup = function (e) {
      //当鼠标弹起来的时候不再移动
      this.onmousemove = null
      //修复低版本ie bug
      if (typeof dragbar.releasePointerCapture != 'undefined') {
        dragbar.releasePointerCapture(pointerId)
      }
    }
  }

  const MakeDragable = function (e) {
    //窗口最大化不可拖动
    if (state.minimize) return
    var eve = e || window.event
    var pointerId = e.pointerId
    const dragbar = e.target
    const CtlEl = dragWin.value
    if (typeof dragbar.setPointerCapture != 'undefined') {
      //SetCapture捕捉鼠标到指定的元素
      //dragAry.setCapture();
      dragbar.setPointerCapture(pointerId)
    }
    CtlEl.style.zIndex = 9999 //当前拖拽的在最前面显示
    const mx = eve.clientX //鼠标点击时的坐标
    const my = eve.clientY //鼠标点击时的坐标
    const dleft = CtlEl.offsetLeft //窗口初始位置
    const dtop = CtlEl.offsetTop
    const clientWidth = document.documentElement.clientWidth //页面的宽
    const oWidth = CtlEl.offsetWidth //窗口的宽
    const maxX = clientWidth - oWidth // x轴能移动的最大距离
    const clientHeight = document.documentElement.clientHeight //页面的高
    const oHeight = CtlEl.offsetHeight //窗口的高度
    const maxY = clientHeight - oHeight //y轴能移动的最大距离

    document.onmousemove = function (e) {
      const x = e.clientX
      const y = e.clientY
      let left = x - mx + dleft //移动后的新位置
      let top = y - my + dtop //移动后的新位置
      if (left < 0) left = 0
      if (left > maxX) left = maxX
      if (top < 0) top = 0
      if (top > maxY) top = maxY

      state.initLeft = left + 'px'
      state.initTop = top + 'px'
      /*
    CtlEl.style.left = left + "px";
    CtlEl.style.top = top + "px";
    CtlEl.style.marginLeft = 0;
    CtlEl.style.marginTop = 0;
    */
    }
    document.onmouseup = function (e) {
      //当鼠标弹起来的时候不再移动
      document.onmousemove = null
      document.onmouseup = null //预防鼠标弹起来后还会循环（即预防鼠标放上去的时候还会移动）
      if (typeof dragbar.releasePointerCapture != 'undefined') {
        dragbar.releasePointerCapture(pointerId)
      }
    }
  }

  // 事件定义
  const emits = defineEmits(['update:modelValue', 'close', 'confirm', 'cancel'])
  /** 方法定义 */
  // 内部控制窗口开关
  const win_close = () => {
    emits('close')
    emits('update:modelValue', !props.modelValue)
  }

  // 确认保存
  const confirm = () => {
    emits('confirm')
  }

  // 取消操作
  const cancel = () => {
    if (props.isVerify) return emits('cancel')
    emits('update:modelValue', !props.modelValue)
  }

  //暴露属性
  defineExpose({ state })

  //传递监听方法给子组件
  const provideData = () => {
    return {
      close: win_close,
    }
  }
  provide('provideData', provideData)

  function FormatNum(value) {
    let val = value
    if (value.indexOf('px') != '-1') {
      val = value.split('px')[0]
    }
    return parseFloat(val)
  }
  const Initializer = function () {
    var height = FormatNum(props.initHeight)
    var width = FormatNum(props.initWidth)
    var atop = (window.innerHeight - height) / 2
    var aleft = (window.innerWidth - width) / 2
    //默认居中
    if (!props.initLeft) {
      state.initLeft = aleft + 'px'
      state.initTop = width + 'px'
    }
    if (!props.initTop) {
      state.initTop = atop + 'px'
    }
    if (props.defaultMax) win_max()
  }

  // defineExpose({ state })

  onDeactivated(() => {
    // 路由改变时，关闭弹窗
    emits('update:modelValue', false)
  })

  onBeforeMount(() => {})
  onMounted(() => {
    nextTick(() => {
      const body = document.querySelector('body')
      if (body.append) {
        body.append(_this.$el)
      } else {
        body.appendChild(_this.$el)
      }
      Initializer()
    })
  })
  onBeforeUpdate(() => {})
  onUpdated(() => {})
</script>

<style scoped rel="stylesheet/scss" lang="scss">
  .flex-row {
    display: flex;
    display: inline-flex;
    display: -webkit-flex;
    /* Safari */
    flex-direction: row;
    flex-wrap: wrap;
  }

  .flex-column {
    display: flex;
    display: inline-flex;
    display: -webkit-flex;
    /* Safari */
    flex-direction: column;
  }

  .modal {
    width: 100%;
    height: 100%;
    position: fixed;
    z-index: 2022;
    top: 0px;
    left: 0px;
    justify-content: center;
    align-items: center;
    background-color: rgba(0, 0, 0, 0.4);
  }

  /*-------窗口组件------*/
  .v-window-container {
    position: fixed;
    z-index: 2023;
    border: 0;
    /*1px solid lightgray;*/
    box-sizing: border-box;
    /*box-shadow: 1px 1px 5px gray;*/
    display: flex;
    flex-direction: column;
    border: 0.5px solid #409eff;
    background-color: #fff;
  }

  .v-window-title {
    height: 30px;
    //border-bottom: 0.5px solid #409EFF;
    user-select: none;
    //background-color: #409EFF;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    color: #fff;
  }

  .v-window-title:hover {
    cursor: move;
  }

  .v-window-btn {
    border: none;
    background: none;
    outline: none;
    color: #fff;
    cursor: pointer;
  }

  .v-window-body {
    flex: 1;
    position: relative;
    width: 100%;
    height: calc(100% - 30px);
    padding: 12px;

    .v-window-content {
      height: 100%;
      overflow-x: hidden;
      overflow-y: auto;
    }
    .v-window-footer {
      display: flex;
      height: 40px;
      justify-content: center;
      align-items: center;
      margin-right: 8px;

      button {
        min-width: 80px;
      }
    }
  }

  .v-window-resizable {
    position: absolute;
    width: 30px;
    height: 30px;
    bottom: 0;
    right: 0;
    background-image: url('');
    background-position-x: 0%;
    background-position-y: 0%;
    background-repeat: repeat;
    background-origin: padding-box;
    background-position: 100% 100%;
    padding: 0 0px 0px 0;
    background-repeat: no-repeat;
    background-origin: content-box;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    cursor: nwse-resize;
    color: aqua;
    z-index: 10;
  }

  :deep(.el-form-item) {
    // width: 85%;
    width: 100%;
    margin-bottom: 12px;
  }

  :deep(.el-input),
  :deep(.el-input-number),
  :deep(.el-select),
  :deep(.el-textarea),
  :deep(.el-input__wrapper) {
    width: 100%;
  }
</style>
